import React, { ReactNode, createContext, forwardRef, useImperativeHandle } from 'react'
import { ValidateError } from 'async-validator' // 表单校验
import useStore, { FormState } from './useStore'
export type RenderProps = (form: FormState) => ReactNode
export interface FormProps {
  name?: string // 表单名称，会作为表单字段 id 前缀使用
  initialValues?: Record<string, any> // 表单默认值，只有初始化以及重置时生效
  children?: ReactNode | RenderProps
  onFinish?: (values: Record<string, any>) => void // 提交表单且数据验证成功后回调事件
  /**提交表单且数据验证失败后回调事件 */
  onFinishFailed?: (values: Record<string, any>, errors: Record<string, ValidateError[]>) => void
}

type IStore = ReturnType<typeof useStore>
export type IFormContext = Pick<IStore, 'dispatch' | 'fields' | 'validateField'> & Pick<FormProps, 'initialValues'>
export const FormContext = createContext<IFormContext>({} as IFormContext)
export type IFormRef = Omit<IStore, 'fields' | 'dispatch' | 'form'>

export const Form = forwardRef<IFormRef, FormProps>((props, ref) => {
  const {
    name = 'dog_form', // 表单名称，会作为表单字段 id 前缀使用
    children,
    initialValues,
    onFinish,
    onFinishFailed
  } = props

  const {
    form, // 表单状态
    fields, // reducer
    dispatch,
    validateField, // 校验单个字段
    validateAllFields, // 校验所有字段
    ...restProps
  } = useStore(initialValues)

  // 暴露给父组件的方法
  useImperativeHandle(ref, () => {
    return {
      validateField, // 校验单个字段
      validateAllFields, // 校验所有字段
      ...restProps
    }
  })

  // 提交表单
  const submitForm = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault()
    e.stopPropagation()
    const { isValid, errors, values } = await validateAllFields()
    await validateAllFields()
    !isValid && console.warn('isValid', isValid)
    if (isValid) {
      onFinish?.(values)
    } else if (!isValid && onFinishFailed) {
      console.warn('errors', errors)
      onFinishFailed(values, errors)
    }
  }

  return (
    <form name={name} className="dog-form" onSubmit={submitForm}>
      <FormContext.Provider
        value={{
          dispatch,
          fields, // reducer
          validateField,
          initialValues // 表单默认值，只有初始化以及重置时生效
        }}
      >
        {typeof children === 'function' ? children(form) : children}
      </FormContext.Provider>
    </form>
  )
})
export default Form
